package main

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

func main() {
	chanTest()
}

var lock sync.Mutex

func chanTest() {
	res := make(chan map[int]int, 200)

	for i := 1; i <= 20; i++ {
		go jieChannel(res, i)
	}
	for re := range res {
		for i, v := range re {
			fmt.Println(i, "的阶乘:", v)
		}
	}
}
func jieChannel(ch chan map[int]int, n int) {
	res := 1
	for i := 1; i <= n; i++ {
		res *= i

	}
	ch <- map[int]int{n: res}
	if n == 20 {
		close(ch)
	}
}

func lockTest() {
	res := make(map[int]int, 200)

	for i := 1; i <= 20; i++ {
		go jieLock(i, res)
	}
	lock.Lock()
	for i, v := range res {
		fmt.Println(strconv.Itoa(i) + "->" + strconv.Itoa(v))
	}
	lock.Unlock()
}

//操作 map 时加锁
func jieLock(n int, resMap map[int]int) int {
	var res = 1
	for i := 1; i <= n; i++ {
		res *= i
	}
	lock.Lock()
	resMap[n] = res
	lock.Unlock()
	return res
}

//fatal error: concurrent map writes，这样会产生并发写入问题，多协程同时写 map，非安全操作
func test() {
	res := make(map[int]int)

	for i := 1; i < 200; i++ {
		go jie(i, res)
	}
	//fatal error: concurrent map writes
	time.Sleep(time.Second * 60)
	for i, v := range res {
		fmt.Println(strconv.Itoa(i) + "->" + strconv.Itoa(v))
	}
}
func jie(n int, resMap map[int]int) int {
	var res = 1
	for i := 1; i <= n; i++ {
		res *= i
	}
	lock.Lock()
	resMap[n] = res
	lock.Unlock()
	return res
}
